<template>
  <div class="audition9">
    <h3>new操作符做了什么？</h3>
    <p>先来看下不使用new操作符，会发生什么？</p>
    <v-md-preview :text="text1" />
    <p>再来看下使用new操作符后，会发生什么？</p>
    <v-md-preview :text="text2" />
    <p>如果构造函数中返回了一个基本数据类型的值，会发生什么？</p>
    <v-md-preview :text="text3" />
    <p>此时，new操作符并未受到返回值的影响</p>
    <p>如果构造函数中返回了一个复杂数据类型的值，会发生什么？</p>
    <v-md-preview :text="text4" />
    <p>此时，new操作符受到了影响，实例变成了返回值，且无法调用prototype中的属性和方法</p>
    <p>由示例可以得知，new操作符做了以下事情：</p>
    <p>
      <span class="indient">1. 创建了一个空对象</span><br />
      <span class="indient">2. 调用了构造函数</span><br />
      <span class="indient">3. 把构造函数中的this指向了新对象</span><br />
      <span class="indient">4. 把创建的对象指向构造函数的prototype</span><br />
      <span class="indient">5. 如果构造函数中返回了一个复杂数据类型的值，则new生成的对象指向该返回值</span>
    </p>
    <hr>
    <p>根据new做的事情，接下来，自己实现new功能：</p>
    <v-md-preview :text="text5" />
    <p>验证<span class="color">myNew</span>：</p>
    <v-md-preview :text="text6" />
  </div>
</template>

<script>
const prefix = '``` js'
const suffix = '```'
export default {
  name: 'Audition9',
  data() {
    return {
      text1: `${prefix}
        function Star(age) {
          this.age = age
        }
        Star.prototype.sing = 'hello'

        var s1 = Star(18)
        console.log(s1) // undefined
        console.log(s1.age) // 报错
        console.log(s1.sing) // 报错
      \n${suffix}`,
      text2: `${prefix}
        function Star(age) {
          console.log('Star被调用了~')
          this.age = age
        }
        Star.prototype.sing = 'hello'

        var s1 = new Star(18)
        console.log(s1)
        console.log(s1.age)
        console.log(s1.sing)
        // 打印结果：
        /*
          'Star被调用了~'
          {age: 18}
          18
          'hello'
        */
      \n${suffix}`,
      text3: `${prefix}
        function Star(age) {
          this.age = age
          console.log('Star被调用了~')
          return 1
        }
        Star.prototype.sing = function() {
          console.log(this)
        }
        var s1 = new Star(18)
        console.log(s1) // {age: 18}
        s1.sing() // {age: 18}
      \n${suffix}`,
      text4: `${prefix}
        function Star(age) {
          this.age = age
          console.log('Star被调用了~')
          return [1, 2, 3]
        }
        Star.prototype.sing = function() {
          console.log(this)
        }
        var s1 = new Star(18)
        console.log(s1) // [1, 2, 3]
        s1.sing() // Uncaught TypeError: s1.sing is not a function
      \n${suffix}`,
      text5: `${prefix}
        function myNew(Fn, ...args) {
          // 创建一个新的空对象obj
          // 并且obj.__proto__ = Fn.prototype
          var obj = Object.create(Fn.prototype)
          // 将Fn的this指向obj，并调用Fn，用result作为Fn的返回值
          var result = Fn.apply(obj, args)
          // 如果Fn的返回值是Object类型，则返回result,否则返回obj
          return result instanceof Object ? result ? obj
        }
      \n${suffix}`,
      text6: `${prefix}
        function Star(age) {
          this.age = age
          return []
        }
        Star.prototype.sing = 'hello'
        var s1 = myNew(Star, 18)
        console.log(s1) // []
        console.log(s1.age) // undefined
        console.log(s1.sing) // undefined
      \n${suffix}`,
    }
  }
}
</script>

<style>

</style>